﻿using System;
using System.Windows.Forms;
using SampleMessages;
using SimpleServiceBus.Endpoint;
using SimpleServiceBus.Endpoints.Msmq;
using SimpleServiceBus.Endpoints.Msmq.Configuration;
using SimpleServiceBus.Messages.Management.Monitoring;

namespace SampleMonitorClient
{
    internal delegate void NotifyDelegate(string message);

    internal delegate void UpdateEndpointStatusDelegate(EndpointStatusSummaryNotification summary);

    public partial class MainForm : Form
    {
        private IMessagingEndpoint _endpoint;

        public MainForm()
        {
            InitializeComponent();
        }

        public static MainForm Current { get; set; }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            Current = this;

            btnStartStop_Click(null, null);
        }

        private void CreateEndpoint()
        {
            MsmqHelper.EnsureQueue("MonitorClient");
            MsmqHelper.EnsureQueue("EndpointMonitorService");

            _endpoint = MsmqEndpointConfiguration.CreateConfiguredEndpoint(GetType().Assembly);
        }

        private void StartEndpoint()
        {
            Notify("Starting Endpoint");

            _endpoint.Start();

            _endpoint.MessageBus.Subscribe<EndpointStatusSummaryNotification>();
            _endpoint.MessageBus.Subscribe<EndpointOnlineNotification>();
            _endpoint.MessageBus.Subscribe<EndpointOfflineNotification>();
            _endpoint.MessageBus.Subscribe<EndpointStatusExpiredNotification>();
            _endpoint.MessageBus.Subscribe<EndpointErrorNotification>();

            //subscribe to test publications
            _endpoint.MessageBus.Subscribe<TestPublicationMessage>();


            Notify("Endpoint Started");
            btnStartStop.Text = "Stop";
        }

        private void StopEndpoint()
        {
            Notify("Stopping Endpoint");

            _endpoint.Stop();

            Notify("Endpoint Stopped");
            btnStartStop.Text = "Start";
        }

        public void Notify(string message)
        {
            if (InvokeRequired)
            {
                NotifyDelegate marshal = Notify;
                BeginInvoke(marshal, message);
            }
            else
            {
                txtStatus.Text += message + Environment.NewLine;
                txtStatus.Refresh();
            }
        }

        public void UpdateEndpointStatus(EndpointStatusSummaryNotification summary)
        {
            if (InvokeRequired)
            {
                UpdateEndpointStatusDelegate marshal = UpdateEndpointStatus;
                BeginInvoke(marshal, summary);
            }
            else
            {
                //treeManagedNodes.Nodes.Clear();
                foreach (EndpointStatusSummary endpoint in summary.ActiveEndpoints)
                {
                    TreeNode epNode;
                    var found = treeManagedNodes.Nodes.Find(endpoint.EndpointID,false);
                    if (found.Length > 0)
                        epNode = found[0];
                    else
                    {
                        epNode = treeManagedNodes.Nodes.Add(endpoint.EndpointID, endpoint.EndpointID);
                    }

                    epNode.Nodes.Clear();
                    
                    foreach (EndpointMeasurementSummary measurement in endpoint.StatusMeasurements)
                    {
                        var mNode = new TreeNode(measurement.LastMeasurement.Name);
                        mNode.Nodes.Add(measurement.LastMeasurement.Timestamp.ToLocalTime().ToString());
                        mNode.Nodes.Add("Last: " + measurement.LastMeasurement.Value + " " +
                                        measurement.LastMeasurement.UnitOfMeasurement);
                        mNode.Nodes.Add("Avg: " + measurement.Average + " " +
                                        measurement.LastMeasurement.UnitOfMeasurement);
                        mNode.Nodes.Add("Max: " + measurement.Max + " " + measurement.LastMeasurement.UnitOfMeasurement);
                        mNode.Nodes.Add("Min: " + measurement.Min + " " + measurement.LastMeasurement.UnitOfMeasurement);
                        mNode.Nodes.Add("Sample Count: " + measurement.SampleCount);
                        epNode.Nodes.Add(mNode);
                    }
                }
                treeManagedNodes.ExpandAll();
            }
        }

        private void btnStartStop_Click(object sender, EventArgs e)
        {
            try
            {
                if (_endpoint == null)
                {
                    CreateEndpoint();
                }

                if (_endpoint.IsRunning)
                {
                    StopEndpoint();
                }
                else
                {
                    StartEndpoint();
                }
            }
            catch (Exception ex)
            {
                Notify(ex.Message + Environment.NewLine + ex.StackTrace);
                while (ex.InnerException != null)
                {
                    Notify(ex.InnerException.Message + Environment.NewLine + ex.StackTrace);
                    ex = ex.InnerException;
                }
            }
        }

        private void labelControl1_Click(object sender, EventArgs e)
        {
        }

        private void btnPing_Click(object sender, EventArgs e)
        {
            string msg = txtPingMessage.Text;
            string address = optDestination.Text;

            if (!string.IsNullOrEmpty(address))
                _endpoint.MessageBus.Send(new EndpointPingRequest {Message = msg}, address);

            Notify(address + " pinged with message:" + msg + " at " + DateTime.Now.ToUniversalTime() + " UTC");
        }
    }
}